home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / BumpMapping / BumpSelfShadow / bumpselfshadow.cpp next >
C/C++ Source or Header  |  2001-10-08  |  59KB  |  1,828 lines

  1. //-----------------------------------------------------------------------------
  2. // File: BumpSelfShadow.cpp
  3. //
  4. // Desc: Shows how to implement self-shadowing bump mapping
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <Windows.h>
  10. #include <tchar.h>
  11. #include <d3dx8.h>
  12. #include "D3DApp.h"
  13. #include "D3DFont.h"
  14. #include "DXUtil.h"
  15.  
  16. //-----------------------------------------------------------------------------
  17. // Defines, constants, and global variables
  18. //-----------------------------------------------------------------------------
  19.  
  20. // A complex vertex, if we use vertex shaders we can handle this data ourselves
  21. struct BiNormalVertex
  22. {
  23.     FLOAT x,y,z;
  24.     FLOAT u,v;
  25.     FLOAT nx,ny,nz;
  26.     FLOAT bx,by,bz;
  27.     DWORD col;
  28.     INT RefCount;
  29. };
  30.  
  31. struct ShaderVertex
  32. {
  33.     FLOAT x,y,z;
  34.     FLOAT u,v;
  35.     FLOAT nx,ny,nz;
  36.     FLOAT bx,by,bz;
  37. };
  38.  
  39. struct NormalVertex
  40. {
  41.     FLOAT x,y,z;
  42.     FLOAT u,v;
  43.     FLOAT nx,ny,nz;
  44. };
  45.  
  46.  
  47. struct BasicVertex
  48. {
  49.     FLOAT x,y,z;
  50.     DWORD col;
  51.     FLOAT u,v;
  52. };
  53. #define FVF_BASICVERTEX D3DFVF_XYZ|D3DFVF_DIFFUSE| D3DFVF_TEX1 
  54.  
  55.  
  56. //A BasicVertex FVF2
  57. struct BasicVertex2
  58. {
  59.     FLOAT x,y,z;
  60.     DWORD col;
  61.     FLOAT u,v;
  62.     FLOAT u1,v2;
  63. };
  64. #define FVF_BASICVERTEX2 D3DFVF_XYZ|D3DFVF_DIFFUSE| D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1)
  65.  
  66. #define MAXTRIANGLES 4096
  67. #define BASISMAPSIZE 32
  68. #define RENDERTARGSIZE 256
  69.  
  70. struct sTriangle
  71. {
  72.     WORD ind1,ind2,ind3;
  73. };
  74.  
  75.  
  76. class ShadowSet 
  77. {
  78.     sTriangle m_Triangles[MAXTRIANGLES];
  79.     LPDIRECT3DVERTEXBUFFER8 m_pScreenVB;
  80.     LPDIRECT3DVERTEXBUFFER8 m_pShad1;
  81.     LPDIRECT3DVERTEXBUFFER8 m_pVertices;
  82.  
  83.     BiNormalVertex m_TriVertices[MAXTRIANGLES*3];
  84.     
  85.     INT m_iNumTriangles,m_iNumVertices;
  86.     DWORD m_iHeightWidth,m_iHeightHeight;
  87.  
  88.     IDirect3DDevice8 *m_pDev;
  89.  
  90.     // our interleaved horizon maps with the precomputed basis textures
  91.     LPDIRECT3DTEXTURE8 m_pHorizonTextures[4];
  92.     LPDIRECT3DTEXTURE8 m_pBasisTextures[4];
  93.  
  94.     // we render into this buffer and use it as a texture
  95.     LPDIRECT3DTEXTURE8 m_pRenderBuffer;
  96.     LPDIRECT3DTEXTURE8 m_pRenderBuffer2;
  97.     LPDIRECT3DTEXTURE8 m_pTempBuffer;
  98.  
  99.     LPDIRECT3DSURFACE8 m_pOldRenderTarget;
  100.     LPDIRECT3DSURFACE8 m_pOldStencilZ;
  101.  
  102.     LPDIRECT3DTEXTURE8 m_pNormalMap;
  103.  
  104.     LPDIRECT3DTEXTURE8     m_pColorTexture;
  105.     LPDIRECT3DINDEXBUFFER8 m_pIndexBuffer;
  106.  
  107.     D3DXMATRIX  m_matObject;
  108.     D3DXMATRIX  m_matView;
  109.     D3DXMATRIX  m_matProj;
  110.     D3DXMATRIX  m_matTot;
  111.  
  112.     // our shaders
  113.     DWORD m_dwBasisShader;
  114.     DWORD m_dwShadowShader;
  115.     DWORD m_dwBumpShader;
  116.     DWORD m_dwPixShader;
  117.  
  118.     TCHAR m_cColorName[160];
  119.     TCHAR m_cHeightName[160];
  120.     DWORD m_dwHeightLevels;
  121.  
  122.     BOOL m_bInitalize;
  123.     BOOL m_bLoaded;
  124.     BOOL m_bUsePix;
  125.  
  126.     // scratch space for loading/computing the textures
  127.     BYTE* m_pHeightMap[16];
  128.     BYTE* m_pHorizonMap[16];
  129.     BYTE* m_pBasisMap[16];
  130.     BYTE* m_pHorizonComp[4];
  131.     BYTE* m_pBasisComp[4];
  132.  
  133.     // linear basis map
  134.     VOID BuildBasisMap(BYTE *pBasis,FLOAT PrimAngle,FLOAT Angle2);
  135.  
  136.     BOOL BuildInterleavedMap(LPDIRECT3DTEXTURE8 &newTex, BYTE *r, BYTE *g, BYTE *b,
  137.                              BYTE *a, INT width, INT height);
  138.  
  139.     VOID BuildHorizonMap(BYTE *pHor, BYTE*, FLOAT dx, FLOAT dy, INT StepLength,
  140.                          INT iWidth, INT iHeight, BOOL bWrapU, BOOL bWrapV);
  141.  
  142. public:
  143.     ShadowSet(TCHAR *HeightMapName, TCHAR *ColorTexName);
  144.     ShadowSet::~ShadowSet();
  145.  
  146.     VOID ComputeLight(D3DXVECTOR3 &lightDir, D3DXMATRIX *pObject, D3DXMATRIX *pView, D3DXMATRIX *pProj);
  147.     VOID Render(BOOL,BOOL, BOOL, INT left, INT top, INT right, INT bottom);
  148.     VOID SetBuffers(LPDIRECT3DINDEXBUFFER8 pIndex, LPDIRECT3DVERTEXBUFFER8 pVertBuffer,
  149.                     INT iNumFaces, INT iNumVertices);
  150.    
  151.     HRESULT Init(IDirect3DDevice8*, BOOL bUsePix);
  152.     VOID DeleteDeviceObj();
  153.     VOID Restore();
  154.     VOID Invalidate();
  155. };
  156.  
  157.  
  158.  
  159.  
  160. //-----------------------------------------------------------------------------
  161. // Name: class CMyD3DApplication
  162. // Desc: Application class. The base class (CD3DApplication) provides the 
  163. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  164. //       adds functionality specific to this sample program.
  165. //-----------------------------------------------------------------------------
  166. class CMyD3DApplication : public CD3DApplication
  167. {
  168. public:
  169.     CMyD3DApplication();
  170.  
  171.     ShadowSet *m_pShadow;
  172.  
  173.     D3DXMATRIX  m_matObject;
  174.     D3DXMATRIX  m_matView;
  175.     D3DXMATRIX  m_matProj;
  176.     D3DXMATRIX  m_matPosition;
  177.  
  178.     D3DXVECTOR3 m_LightDir;
  179.     BOOL m_bLMouseDown;
  180.     BOOL m_bRMouseDown;
  181.     BOOL m_bFirstTime;
  182.     BOOL m_bRotate;
  183.     FLOAT m_xPos, m_yPos;
  184.     FLOAT m_oPosX, m_oPosY;
  185.     INT m_iIndex;
  186.  
  187.     BYTE  m_bKey[256];
  188.     FLOAT m_fSpeed;
  189.     FLOAT m_fAngularSpeed;
  190.     FLOAT m_fTheta;
  191.     FLOAT m_fTheta2;
  192.  
  193.     BOOL m_bDebug;
  194.     BOOL m_bShadow;
  195.     BOOL m_bBump;
  196.     BOOL m_bUsePix;
  197.  
  198.     D3DXVECTOR3     m_vecVelocity;
  199.     D3DXVECTOR3     m_vecAngularVelocity;
  200.  
  201.     virtual HRESULT OneTimeSceneInit();
  202.     virtual HRESULT InitDeviceObjects();
  203.     virtual HRESULT RestoreDeviceObjects();
  204.     virtual HRESULT InvalidateDeviceObjects();
  205.     virtual HRESULT DeleteDeviceObjects();
  206.     virtual HRESULT FrameMove();
  207.     virtual HRESULT Render();
  208.     virtual LRESULT MsgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  209.     virtual HRESULT ConfirmDevice(D3DCAPS8*,DWORD,D3DFORMAT);
  210.     virtual HRESULT FinalCleanup();
  211.  
  212. private:
  213.     FLOAT m_fAspectRatio;
  214.  
  215.     VOID CreateSphere();
  216.     VOID OnMouseMove();
  217.     VOID LoadXFile(TCHAR*);
  218.  
  219.     CD3DFont* m_pFont;
  220.     CD3DFont* m_pFontSmall;
  221. };
  222.  
  223.  
  224.  
  225. //-----------------------------------------------------------------------------
  226. // Name: WinMain()
  227. // Desc: Entry point to the program. Initializes everything, and goes into a
  228. //       message-processing loop. Idle time is used to render the scene.
  229. //-----------------------------------------------------------------------------
  230. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  231. {
  232.     CMyD3DApplication d3dApp;
  233.  
  234.     if( FAILED( d3dApp.Create( hInst ) ) )
  235.         return 0;
  236.  
  237.     return d3dApp.Run();
  238. }
  239.  
  240.  
  241.  
  242.  
  243. //-----------------------------------------------------------------------------
  244. // Name: ConfirmDevice()
  245. // Desc: Called during device intialization, this code checks the device
  246. //       for some minimum set of capabilities
  247. //-----------------------------------------------------------------------------
  248. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  249.                                           D3DFORMAT Format )
  250. {
  251.     if( (dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||
  252.         (dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) )
  253.     {
  254.         if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,0) )
  255.             return E_FAIL;
  256.     }
  257.       
  258.     if(!(pCaps->TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3))
  259.         return E_FAIL;
  260.     if(pCaps->MaxTextureBlendStages < 2)
  261.         return E_FAIL;
  262.  
  263.     if( pCaps->PixelShaderVersion < D3DPS_VERSION(1,1) )
  264.     {
  265.         if( FAILED( m_pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, 
  266.             pCaps->DeviceType, Format, D3DUSAGE_RENDERTARGET,
  267.             D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8 ) ) )
  268.         {
  269.             return E_FAIL;
  270.         }
  271.     }
  272.  
  273.     return S_OK;
  274. }
  275.  
  276.  
  277.  
  278.  
  279. //-----------------------------------------------------------------------------
  280. // Name: CMyD3DApplication()
  281. // Desc: Application constructor. Sets attributes for the app.
  282. //-----------------------------------------------------------------------------
  283. CMyD3DApplication::CMyD3DApplication()
  284. {
  285.     D3DXMATRIX matT;
  286.     m_fElapsedTime = 0.0f;
  287.     m_fAspectRatio = 0.0f;
  288.  
  289.     m_dwCreationWidth   = 400;   // Width used to create window
  290.     m_dwCreationHeight  = 400;
  291.  
  292.     m_bUseDepthBuffer   = TRUE;
  293.     m_bShowCursorWhenFullscreen = TRUE;
  294.  
  295.     m_strWindowTitle    = _T("Self-Shadow Bumpmap");
  296.  
  297.     m_pShadow = NULL;
  298.     m_pFont         = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  299.     m_pFontSmall    = new CD3DFont( _T("Arial"),  9, D3DFONT_BOLD );
  300.  
  301.     for(INT i=0; i<256; i++)
  302.         m_bKey[i] = FALSE;
  303.  
  304.     m_bLMouseDown = FALSE;
  305.     m_bRMouseDown = FALSE;
  306.     m_bFirstTime  = TRUE;
  307.  
  308.     m_iIndex = 0;
  309.  
  310.     m_bDebug = m_bShadow = m_bBump = TRUE;
  311.   
  312.     m_fTheta             = 0;
  313.     m_fTheta2            = 0;
  314.  
  315.     D3DXMatrixIdentity(&m_matObject);
  316.     D3DXMatrixIdentity(&m_matView);
  317.     D3DXMatrixIdentity(&m_matPosition);
  318.  
  319.     //initalize the camera and keyboard speeds
  320.     //this should probally change depending on the size
  321.     //of the object being viewed
  322.     m_fSpeed             = 20.00f;
  323.     m_fAngularSpeed      =  0.10f;
  324.     m_vecVelocity        = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  325.     m_vecAngularVelocity = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  326.     m_LightDir           = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  327.  
  328.     D3DXMatrixTranslation( &matT, 0,0, -40);
  329.  
  330.     D3DXMatrixMultiply( &m_matPosition, &matT, &m_matPosition );
  331.     D3DXMatrixInverse( &m_matView, NULL, &m_matPosition );
  332. }
  333.  
  334.  
  335.  
  336.  
  337. HRESULT CMyD3DApplication::FinalCleanup()
  338. {
  339.     SAFE_DELETE(m_pShadow);
  340.     
  341.     return S_OK;
  342. }
  343.  
  344.  
  345.  
  346.  
  347. //track mouse movement
  348. //just a crude interface to let the user move the object
  349. VOID CMyD3DApplication::OnMouseMove()
  350. {
  351.     RECT r;
  352.     FLOAT dx,dy;
  353.     D3DXMATRIX mat1,mat2,mat3;
  354.  
  355.     GetWindowRect(m_hWnd,&r);
  356.     dx = ((FLOAT)m_xPos)/((FLOAT)r.right-r.left)*2 - 1;
  357.     dy = ((FLOAT)m_yPos)/((FLOAT)r.right-r.left)*2 - 1;
  358.     
  359.     //right mouse button moves the light around
  360.     if(m_bRMouseDown)
  361.     {
  362.         m_LightDir.x = -dx;
  363.         m_LightDir.y = dy;
  364.         m_LightDir.z = .25f;
  365.     }
  366.     
  367.     //left button rotates the object
  368.     if(m_bLMouseDown)
  369.     {   
  370.         m_fTheta  = -dy+m_oPosY;
  371.         m_fTheta2 = -dx+m_oPosX;
  372.     
  373.         D3DXMatrixRotationX(&mat1,m_fTheta*.1f);
  374.         D3DXMatrixRotationY(&mat2,m_fTheta2*.1f);
  375.         D3DXMatrixMultiply(&mat3,&mat1,&mat2);
  376.         D3DXMatrixMultiply(&m_matObject,&m_matObject,&mat3);
  377.     }
  378. }
  379.  
  380.  
  381.  
  382.  
  383. //-----------------------------------------------------------------------------
  384. // Name: MsgProc()
  385. // Desc: Message proc function to handle key and menu input
  386. //-----------------------------------------------------------------------------
  387. LRESULT CMyD3DApplication::MsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  388. {
  389.     RECT r;
  390.     D3DXMATRIX matT;
  391.  
  392.     // Trap the context menu
  393.     if( WM_CONTEXTMENU==uMsg )
  394.         return 0;
  395.  
  396.     switch(uMsg)
  397.     {
  398.     case WM_KEYUP:
  399.         //mark a key up
  400.         m_bKey[wParam] = FALSE;
  401.         break;
  402.  
  403.     case WM_KEYDOWN:
  404.         //mark a key down
  405.          m_bKey[wParam] = TRUE;
  406.              
  407.          //turn shadowing off
  408.         if(wParam == '2')
  409.             m_bShadow = !m_bShadow;
  410.  
  411.         //turn bump mapping off
  412.         if(wParam == '3')
  413.             m_bBump = !m_bBump;
  414.  
  415.         //auto rotate
  416.         if(wParam == '5')
  417.             m_bRotate = !m_bRotate;
  418.     
  419.         //reset matrices
  420.         if(wParam == '4')
  421.         {
  422.             D3DXMatrixTranslation( &m_matPosition, 0,0, -40);
  423.             D3DXMatrixInverse( &m_matView, NULL, &m_matPosition );
  424.             D3DXMatrixIdentity(&m_matObject);
  425.         }
  426.        break;
  427.  
  428.        //track left mouse button down
  429.     case WM_LBUTTONDOWN:
  430.         m_bLMouseDown=TRUE;
  431.         m_xPos = LOWORD(lParam);
  432.         m_yPos = HIWORD(lParam);
  433.  
  434.         GetWindowRect(m_hWnd,&r);
  435.         
  436.         m_oPosX = ((FLOAT)m_xPos)/((FLOAT)r.right-r.left)*2 - 1;
  437.         m_oPosY = ((FLOAT)m_yPos)/((FLOAT)r.right-r.left)*2 - 1;
  438.         break;
  439.  
  440.         //track right mouse button 
  441.     case WM_RBUTTONDOWN:
  442.         m_xPos = LOWORD(lParam);
  443.         m_yPos = HIWORD(lParam);
  444.     
  445.         m_bRMouseDown = TRUE;
  446.         break;
  447.  
  448.         //track mouse movement
  449.     case  WM_MOUSEMOVE:
  450.         if(m_bRMouseDown || m_bLMouseDown)
  451.         {
  452.             m_xPos = LOWORD(lParam);
  453.             m_yPos = HIWORD(lParam);
  454.         }
  455.  
  456.         OnMouseMove();
  457.         break;
  458.  
  459.     case WM_RBUTTONUP:
  460.         m_bRMouseDown=FALSE;
  461.         break;
  462.  
  463.     case WM_LBUTTONUP:
  464.         m_bLMouseDown=FALSE;
  465.         break;
  466.     }
  467.  
  468.     return CD3DApplication::MsgProc( hwnd, uMsg, wParam, lParam );
  469. }
  470.  
  471.  
  472.  
  473.  
  474. //load an X file
  475. VOID CMyD3DApplication::LoadXFile(TCHAR* name)
  476. {
  477.     LPD3DXMESH           pMeshSysMem=NULL,pMeshSysMem2=NULL;
  478.     LPDIRECT3DINDEXBUFFER8 pIndexBuffer=NULL;
  479.    
  480.     HRESULT hr;
  481.     DWORD                dwFaces,dwVertices;
  482.  
  483.     LPDIRECT3DVERTEXBUFFER8 pVertexBuffer = NULL;
  484.   
  485.     hr = D3DXLoadMeshFromX(name, D3DXMESH_SYSTEMMEM, 
  486.                           m_pd3dDevice, NULL, NULL, NULL, &pMeshSysMem);
  487.     if(FAILED(hr))
  488.         goto FAIL;
  489.  
  490.     //reform the mesh to one which will have space for the tangent vectors
  491.     hr = pMeshSysMem->CloneMeshFVF(D3DXMESH_MANAGED,  D3DFVF_NORMAL
  492.                                     | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_XYZ, 
  493.                                     m_pd3dDevice, &pMeshSysMem2);
  494.  
  495.     //compute the normals
  496.     hr = D3DXComputeNormals(pMeshSysMem,NULL);
  497.     if(FAILED(hr))
  498.         goto FAIL;
  499.  
  500.     //compute the tangent vectors in the texture space and load them into
  501.     //the 1'rd texture stage (which is 3d), read the texture coords from the 0th texture
  502.     //stage. Don't need the V direction vector since it is assumed to be U x N.
  503.     hr = D3DXComputeTangent(pMeshSysMem,0,pMeshSysMem2,1,D3DX_COMP_TANGENT_NONE,TRUE,NULL);
  504.     if(FAILED(hr))
  505.         goto FAIL;
  506.          
  507.     SAFE_RELEASE(pMeshSysMem);
  508.  
  509.     hr = pMeshSysMem2->GetIndexBuffer(&pIndexBuffer);
  510.     if(FAILED(hr))
  511.         goto FAIL;
  512.     hr = pMeshSysMem2->GetVertexBuffer(&pVertexBuffer);
  513.     if(FAILED(hr))
  514.         goto FAIL;
  515.  
  516.     dwFaces    = pMeshSysMem2->GetNumFaces();
  517.     dwVertices = pMeshSysMem2->GetNumVertices();
  518.     
  519.     //give them to the shadow object
  520.     m_pShadow->SetBuffers(pIndexBuffer,pVertexBuffer,dwFaces,dwVertices);
  521.  
  522.     SAFE_RELEASE(pVertexBuffer)
  523.     SAFE_RELEASE(pIndexBuffer)
  524.  
  525.     //cleanup
  526. FAIL:
  527.       
  528.     SAFE_RELEASE(pMeshSysMem)
  529.     SAFE_RELEASE(pMeshSysMem2)
  530.     SAFE_RELEASE(pVertexBuffer)
  531.     SAFE_RELEASE(pIndexBuffer)
  532. }
  533.  
  534.  
  535.  
  536. //-----------------------------------------------------------------------------
  537. // Name: FrameMove()
  538. // Desc: Animates the scene
  539. //-----------------------------------------------------------------------------
  540. HRESULT CMyD3DApplication::FrameMove()
  541. {
  542.     D3DXMATRIX matWorld,mat1,mat2;
  543.  
  544.     // Update world matrix
  545.     
  546.      // Process keyboard input
  547.     D3DXVECTOR3 vecT(0.0f, 0.0f, 0.0f);
  548.     D3DXVECTOR3 vecR(0.0f, 0.0f, 0.0f);
  549.  
  550.     vecT =     D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  551.     if(m_bKey['W'])                            vecT.z += 2.0f; // Move Forward
  552.     if(m_bKey['S'])                            vecT.z -= 2.0f; // Move Backward
  553.    
  554.     m_vecVelocity = m_vecVelocity * 0.9f - vecT * 0.1f;
  555.     m_vecAngularVelocity = m_vecAngularVelocity * 0.9f - vecR * 0.1f;
  556.  
  557.        // Update position and view matricies
  558.     D3DXMATRIX matT, matR;
  559.     D3DXQUATERNION qR;
  560.  
  561.     vecT = m_vecVelocity * m_fElapsedTime * m_fSpeed;
  562.     vecR = m_vecAngularVelocity * m_fElapsedTime * m_fAngularSpeed;
  563.  
  564.     D3DXMatrixTranslation( &matT, -vecT.x, -vecT.y, -vecT.z );
  565.      
  566.     D3DXMatrixMultiply( &m_matPosition, &matT, &m_matPosition );
  567.  
  568.     D3DXQuaternionRotationYawPitchRoll( &qR, vecR.y, vecR.x, vecR.z );
  569.     D3DXMatrixRotationQuaternion( &matR, &qR );
  570.     D3DXMatrixMultiply( &m_matPosition, &matR, &m_matPosition );
  571.  
  572.     D3DXMatrixInverse( &m_matView, NULL, &m_matPosition );
  573.  
  574.     //apply rotation
  575.     if(m_bRotate)
  576.     {
  577.         D3DXMatrixRotationY(&matR, -m_fElapsedTime*.5f);
  578.         D3DXMatrixMultiply(&m_matObject,&matR,&m_matObject);
  579.     }
  580.  
  581.     return S_OK;
  582. }
  583.  
  584.  
  585.  
  586.  
  587. //-----------------------------------------------------------------------------
  588. // Name: Render()
  589. // Desc: Renders the scene.
  590. //-----------------------------------------------------------------------------
  591. HRESULT CMyD3DApplication::Render()
  592. {
  593.     HRESULT hr;
  594.     
  595.     FLOAT fAspectRatio = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  596.   
  597.     // Update projection matrix
  598.     if(m_fAspectRatio != fAspectRatio)
  599.     {
  600.         D3DXMATRIX matProjection;
  601.         D3DXMatrixPerspectiveFovLH(&m_matProj, 0.05f, fAspectRatio, 1.0f, 10000.0f);
  602.         m_fAspectRatio = fAspectRatio;
  603.     }
  604.  
  605.     m_pShadow->ComputeLight(m_LightDir,&m_matObject,&m_matView,&m_matProj); 
  606.    
  607.     if(FAILED(hr = m_pd3dDevice->BeginScene()))
  608.         return hr;
  609.  
  610.     
  611.     if(m_bWindowed)
  612.     {
  613.         m_pShadow->Render(m_bDebug, m_bShadow, m_bBump, m_rcWindowClient.left,
  614.                           m_rcWindowClient.top, m_rcWindowClient.right - m_rcWindowClient.left,
  615.                           m_rcWindowClient.bottom - m_rcWindowClient.top);
  616.     }
  617.     else
  618.     {
  619.         m_pShadow->Render(m_bDebug, m_bShadow, m_bBump, 0, 0, 
  620.                           m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height);
  621.     }
  622.  
  623.     // Output statistics
  624.     m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  625.     m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  626.     m_pFontSmall->DrawText( 2, 40, D3DCOLOR_ARGB(255,255,255,255), TEXT("2: Toggle shadow") );
  627.     m_pFontSmall->DrawText( 2, 60, D3DCOLOR_ARGB(255,255,255,255), TEXT("3: Toggle bumpmapping") );
  628.     m_pFontSmall->DrawText( 2, 80, D3DCOLOR_ARGB(255,255,255,255), TEXT("4: Reset object") );
  629.     m_pFontSmall->DrawText( 2,100, D3DCOLOR_ARGB(255,255,255,255), TEXT("5: Toggle spin") );
  630.  
  631.     if(FAILED(hr = m_pd3dDevice->EndScene()))
  632.         return hr;
  633.  
  634.     return S_OK;
  635. }
  636.  
  637.  
  638.  
  639.  
  640. //-----------------------------------------------------------------------------
  641. // Name: OneTimeSceneInit()
  642. // Desc: Called during initial app startup, this function performs all the
  643. //       permanent initialization.
  644. //-----------------------------------------------------------------------------
  645. HRESULT CMyD3DApplication::OneTimeSceneInit()
  646.  
  647. {
  648.     // Set cursor to indicate that user can move the object with the mouse
  649. #ifdef _WIN64
  650.     SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor( NULL, IDC_SIZEALL ) );
  651. #else
  652.     SetClassLong( m_hWnd, GCL_HCURSOR, (LONG)LoadCursor( NULL, IDC_SIZEALL ) );
  653. #endif
  654.  
  655.     TCHAR strBump[160], strColor[160];
  656.     DXUtil_FindMediaFile(strBump, _T("earthbump.bmp"));
  657.     DXUtil_FindMediaFile(strColor,_T("earth.bmp"));
  658.  
  659.     m_pShadow = new ShadowSet(strBump, strColor);
  660.     return S_OK;
  661. }
  662.  
  663.  
  664.  
  665.  
  666. //-----------------------------------------------------------------------------
  667. // Name: InitDeviceObjects()
  668. // Desc: Initialize scene objects.
  669. //-----------------------------------------------------------------------------
  670. HRESULT CMyD3DApplication::InitDeviceObjects()
  671. {
  672.     D3DXMATRIX matT;
  673.  
  674.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  675.     m_pFontSmall->InitDeviceObjects( m_pd3dDevice );
  676.  
  677.     D3DXMatrixIdentity(&m_matObject);
  678.     D3DXMatrixIdentity(&m_matView);
  679.     D3DXMatrixIdentity(&m_matPosition);
  680.  
  681.     m_fSpeed             = 20.0f;
  682.     m_fAngularSpeed      = .10f;
  683.     m_vecVelocity        = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  684.     m_vecAngularVelocity = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  685.     m_LightDir           = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  686.  
  687.     D3DXMatrixTranslation( &matT, 0,0, -40);
  688.  
  689.     D3DXMatrixMultiply( &m_matPosition, &matT, &m_matPosition );
  690.     D3DXMatrixInverse( &m_matView, NULL, &m_matPosition );
  691.    
  692.     D3DCAPS8 Caps;
  693.     m_pd3dDevice->GetDeviceCaps(&Caps);
  694.  
  695.     //detect if the hardware supports pixel shaders
  696.     //if it does, then the shadow term can be done in one pass,
  697.     //resulting in much faster and better results
  698.     if(Caps.PixelShaderVersion < D3DPS_VERSION(1,1) )
  699.         m_bUsePix = FALSE;
  700.     else
  701.         m_bUsePix = TRUE;
  702.  
  703.     if(FAILED( m_pShadow->Init(m_pd3dDevice, m_bUsePix)))
  704.        return E_FAIL;
  705.  
  706.     TCHAR strFile[160];
  707.     DXUtil_FindMediaFile(strFile, _T("sphere.x"));
  708.     LoadXFile(strFile);
  709.  
  710.     return S_OK;
  711. }
  712.  
  713.  
  714.  
  715.  
  716. //-----------------------------------------------------------------------------
  717. // Name: RestoreDeviceObjects()
  718. // Desc: Initialize scene objects.
  719. //-----------------------------------------------------------------------------
  720. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  721. {
  722.     m_pFont->RestoreDeviceObjects();
  723.     m_pFontSmall->RestoreDeviceObjects();
  724.  
  725.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  726.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);     
  727.    
  728.     m_pShadow->Restore();
  729.  
  730.     return S_OK;
  731. }
  732.  
  733.  
  734.  
  735.  
  736. //-----------------------------------------------------------------------------
  737. // Name: InvalidateDeviceObjects()
  738. // Desc:
  739. //-----------------------------------------------------------------------------
  740. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  741. {
  742.     m_pFont->InvalidateDeviceObjects();
  743.     m_pFontSmall->InvalidateDeviceObjects();
  744.     m_pShadow->Invalidate();
  745.     return S_OK;
  746. }
  747.  
  748.  
  749.  
  750.  
  751. //-----------------------------------------------------------------------------
  752. // Name: DeleteDeviceObjects()
  753. // Desc: Called when the app is exiting, or the device is being changed,
  754. //       this function deletes any device dependent objects.
  755. //-----------------------------------------------------------------------------
  756. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  757. {
  758.     m_pFont->DeleteDeviceObjects();
  759.     m_pFontSmall->DeleteDeviceObjects();
  760.     m_pShadow->DeleteDeviceObj();
  761.     return S_OK;
  762. }
  763.  
  764.  
  765.  
  766.  
  767. ShadowSet::ShadowSet(TCHAR *name,TCHAR *colorName)
  768. {
  769.     DWORD i,x,y;
  770.     FLOAT fRange = D3DX_PI/4;
  771.  
  772.     m_bInitalize = FALSE;
  773.     m_bLoaded = FALSE;
  774.  
  775.     DWORD dwIndex =0;
  776.    
  777.     m_pOldStencilZ=NULL;
  778.  
  779.     //set everything to NULL
  780.     for(i = 0;i < 16;i++)
  781.     {
  782.         m_pBasisMap[i] = NULL;
  783.         m_pHorizonMap[i] = NULL;
  784.         m_pHeightMap[i] = NULL;
  785.         if(i<4)
  786.         {
  787.             m_pBasisTextures[i] = NULL;
  788.             m_pHorizonTextures[i] = NULL;
  789.         }
  790.     }   
  791.  
  792.     m_pRenderBuffer  = NULL;
  793.     m_pRenderBuffer2 = NULL;  
  794.  
  795.     m_pNormalMap        = NULL;
  796.     m_pColorTexture     = NULL;
  797.   
  798.     if(colorName)
  799.         _tcscpy(m_cColorName,colorName);
  800.     else
  801.         m_cColorName[0] = 0;
  802.  
  803.     if(name)
  804.         _tcscpy(m_cHeightName,name);
  805.     else
  806.         m_cColorName[0] = 0;
  807.  
  808.     //Load Bitmap
  809.     RGBQUAD rgbq[256];
  810.     BITMAP bp;
  811.     BYTE *bits;
  812.     BYTE *tb;
  813.     HBITMAP texmap;
  814.     HDC tDC;
  815.     BYTE *temploc,*srcloc;
  816.     
  817.     texmap = (HBITMAP)LoadImage(NULL, name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
  818.     if(texmap==0)
  819.         goto FAIL;
  820.     GetObject(texmap, sizeof(BITMAP), (LPSTR) &bp);
  821.  
  822.     m_iHeightWidth  = bp.bmWidth;
  823.     m_iHeightHeight = bp.bmHeight;
  824.  
  825.     //XXX - need to  check for powers of 2
  826.     tDC = CreateCompatibleDC(NULL);
  827.     SelectObject(tDC, texmap);
  828.     GetObject(tDC, sizeof(BITMAP), (LPSTR) &bp);
  829.     bits = (BYTE *)bp.bmBits;
  830.  
  831.     GetDIBColorTable(tDC,0,256,rgbq);
  832.  
  833.     tb = m_pHeightMap[0] = new BYTE[m_iHeightWidth*m_iHeightHeight];
  834.     if(tb==NULL)
  835.         goto FAIL;
  836.  
  837.     if(bp.bmBitsPixel == 8)
  838.     {
  839.       for(y = 0; y < m_iHeightHeight; y++)
  840.       { 
  841.         for(x = 0; x < m_iHeightWidth ; x++)
  842.         {
  843.             temploc = &tb[(y * (m_iHeightWidth) + x) ];
  844.             srcloc = &bits[(m_iHeightHeight-y-1) * (bp.bmWidthBytes) + x];
  845.             temploc[0] = rgbq[*srcloc].rgbRed;
  846.         }
  847.       }
  848.     }
  849.     else
  850.     {
  851.         for(y = 0; y < m_iHeightHeight; y++)
  852.         { 
  853.             for(x = 0; x < m_iHeightWidth ; x++)
  854.             {
  855.                 temploc = &tb[(y * (m_iHeightWidth) + x)];
  856.                 srcloc = &bits[(m_iHeightHeight-y-1) * (bp.bmWidthBytes) + x*3];
  857.                 temploc[0] = srcloc[2];
  858.             }
  859.         }
  860.     }
  861.  
  862.     DeleteObject(texmap);
  863.     DeleteDC(tDC);
  864.  
  865.     DWORD curHeight,curWidth;
  866.  
  867.     curHeight = m_iHeightHeight;
  868.     curWidth  = m_iHeightWidth;
  869.  
  870.     curHeight = curHeight >> 1;
  871.     curWidth  = curWidth  >> 1;
  872.  
  873.  /*   for(i = 1;(curHeight > 2) && (curWidth > 2);i++)
  874.     {
  875.    
  876.         m_pHeightMap[i] = new BYTE[curHeight*curWidth];
  877.         if(!m_pHeightMap)
  878.             goto FAIL;
  879.  
  880.          //do an average of the four neighboring pixels of the previous level
  881.         for(y = 0;y < curHeight;y++)
  882.         {
  883.             pLine = &m_pHeightMap[i-1][y*2*(2*curWidth)];
  884.             for(x = 0; x < curWidth;x++)
  885.             {
  886.                 m_pHeightMap[i][y*curWidth+x] = (pLine[0] + pLine[1] +
  887.                                                        pLine[2*curWidth]+pLine[2*curWidth+1])/4;    
  888.                 pLine+=2;
  889.             }
  890.         }
  891.         curHeight = curHeight >> 1;
  892.         curWidth  = curWidth  >> 1;
  893.     }
  894.     m_dwHeightLevels = i;
  895.  
  896.   */
  897.     //now set up the basis maps
  898.     for(i = 0;i < 8;i++)
  899.     {
  900.         m_pBasisMap[i] = new BYTE[BASISMAPSIZE*BASISMAPSIZE];
  901.         m_pHorizonMap[i] = new BYTE[m_iHeightWidth*m_iHeightHeight];
  902.  
  903.         if(m_pBasisMap[i] == NULL ||
  904.            m_pHorizonMap[i] == NULL)
  905.             goto FAIL;
  906.     
  907.         BuildBasisMap(m_pBasisMap[i],((FLOAT)(D3DX_PI*i))/4.0f,fRange);
  908.         BuildHorizonMap(m_pHorizonMap[i],m_pHeightMap[0],cosf((FLOAT)(D3DX_PI*i)/4.0f), sinf((FLOAT)(D3DX_PI*i)/4.0f),15,m_iHeightWidth,
  909.                         m_iHeightHeight,TRUE,TRUE);
  910.     }
  911.  
  912.     m_pShad1 = NULL;
  913.     m_pRenderBuffer = NULL;
  914.     m_pIndexBuffer = NULL;
  915.     m_pScreenVB=NULL;
  916.  
  917.     m_iNumTriangles = 0;
  918.     m_iNumVertices  = 0;
  919.     m_pVertices = NULL;
  920.  
  921.     m_bLoaded = TRUE;
  922.     return;
  923.  
  924. FAIL:
  925.     return;
  926. }
  927.  
  928.  
  929.  
  930.  
  931. ShadowSet::~ShadowSet()
  932. {
  933.     INT i;
  934.   
  935.     for(i = 0;i < 16;i++)
  936.     {
  937.         if(m_pBasisMap[i])
  938.             delete []m_pBasisMap[i]; 
  939.         if(m_pHorizonMap[i])
  940.             delete []m_pHorizonMap[i];
  941.         if(m_pHeightMap[i])
  942.             delete []m_pHeightMap[i];
  943.     }
  944. }
  945.  
  946.  
  947.  
  948.  
  949. HRESULT ShadowSet::Init(IDirect3DDevice8 *pDev, BOOL bUsePix)
  950. {
  951.     HRESULT hr;
  952.     LPD3DXBUFFER pCode=NULL;
  953.     INT iWidth,iHeight;
  954.     m_pDev = pDev;
  955.  
  956.     LPDIRECT3DTEXTURE8 pHeightMap;
  957.     D3DSURFACE_DESC    desc;
  958.     
  959.     DWORD dwDecl[] = 
  960.     {
  961.         D3DVSD_STREAM(0),
  962.         D3DVSD_REG(0,   D3DVSDT_FLOAT3),
  963.         D3DVSD_REG(3,   D3DVSDT_FLOAT3),
  964.         D3DVSD_REG(7,   D3DVSDT_FLOAT2),
  965.         D3DVSD_REG(8,   D3DVSDT_FLOAT3),
  966.         D3DVSD_END()
  967.     };
  968.  
  969.     TCHAR Shad1[255],Shad2[255],Shad3[255];
  970.  
  971.     m_bUsePix = bUsePix;
  972.     if(!m_bLoaded)
  973.         goto FAIL;
  974.  
  975.     if(FAILED(hr = D3DXCreateTextureFromFile(m_pDev,m_cColorName,&m_pColorTexture)))
  976.         goto FAIL;
  977.  
  978.     if(FAILED(hr = D3DXCreateTextureFromFile(m_pDev,m_cHeightName,&pHeightMap)))
  979.         goto FAIL;
  980.  
  981.     pHeightMap->GetLevelDesc(0,&desc);
  982.  
  983.     iWidth  = desc.Width;
  984.     iHeight = desc.Height;
  985.     
  986.     if(FAILED(hr = D3DXCreateTexture(m_pDev,iWidth,iHeight,0,0,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED, &m_pNormalMap)))
  987.         goto FAIL;
  988.  
  989.     D3DXComputeNormalMap(m_pNormalMap,pHeightMap,NULL,0,D3DX_CHANNEL_RED,10);
  990.     
  991.     pHeightMap->Release();
  992.  
  993.     //two methods
  994.     if(!m_bUsePix)
  995.     {
  996.         //don't have a dp4, so need to put the maps into 3 basis texture and 3 horizon maps
  997.         //basis maps are not-content specific - they are just LERP tables
  998.  
  999.         //build the interleave maps
  1000.         if(!BuildInterleavedMap(m_pBasisTextures[0],m_pBasisMap[0],m_pBasisMap[1],m_pBasisMap[2],NULL,BASISMAPSIZE,BASISMAPSIZE))
  1001.             goto FAIL;
  1002.         if(!BuildInterleavedMap(m_pBasisTextures[1],m_pBasisMap[3],m_pBasisMap[4],m_pBasisMap[5],NULL,BASISMAPSIZE,BASISMAPSIZE))
  1003.             goto FAIL;
  1004.         if(!BuildInterleavedMap(m_pBasisTextures[2],m_pBasisMap[6],m_pBasisMap[7],NULL,NULL,BASISMAPSIZE,BASISMAPSIZE))
  1005.             goto FAIL;
  1006.  
  1007.         if(!BuildInterleavedMap(m_pHorizonTextures[0],m_pHorizonMap[0],m_pHorizonMap[1],m_pHorizonMap[2],NULL,m_iHeightWidth,m_iHeightHeight))
  1008.             goto FAIL;
  1009.         if(!BuildInterleavedMap(m_pHorizonTextures[1],m_pHorizonMap[3],m_pHorizonMap[4],m_pHorizonMap[5],NULL,m_iHeightWidth,m_iHeightHeight))
  1010.            goto FAIL;
  1011.         if(!BuildInterleavedMap(m_pHorizonTextures[2],m_pHorizonMap[6],m_pHorizonMap[7],NULL,NULL,m_iHeightWidth,m_iHeightHeight))
  1012.            goto FAIL;
  1013.  
  1014.         if(FAILED(hr = D3DXFilterTexture(m_pHorizonTextures[0],NULL,0,D3DX_FILTER_BOX)))
  1015.             goto FAIL;
  1016.         if(FAILED(hr = D3DXFilterTexture(m_pHorizonTextures[1],NULL,0,D3DX_FILTER_BOX)))
  1017.             goto FAIL;
  1018.         if(FAILED(hr = D3DXFilterTexture(m_pHorizonTextures[2],NULL,0,D3DX_FILTER_BOX)))
  1019.             goto FAIL;
  1020.   
  1021.         DXUtil_FindMediaFile(Shad1,_T("bumpshader.vsh"));
  1022.         DXUtil_FindMediaFile(Shad2,_T("bumpshader2.vsh"));
  1023.         DXUtil_FindMediaFile(Shad3,_T("bumpshader3.vsh"));
  1024.  
  1025.         if( FAILED( hr = D3DXAssembleShaderFromFile(Shad2, 0, NULL, &pCode, NULL ) ) )
  1026.             goto FAIL;
  1027.         if( FAILED( hr = m_pDev->CreateVertexShader( dwDecl,(DWORD*)pCode->GetBufferPointer(), &m_dwBasisShader, 0 ) ) )
  1028.             goto FAIL;      
  1029.         SAFE_RELEASE(pCode);
  1030.         
  1031.         if( FAILED( hr = D3DXAssembleShaderFromFile(Shad1, 0, NULL, &pCode, NULL ) ) )
  1032.             goto FAIL;
  1033.         if( FAILED( hr = m_pDev->CreateVertexShader( dwDecl,(DWORD*)pCode->GetBufferPointer(), &m_dwShadowShader, 0 ) ) )
  1034.             goto FAIL;
  1035.         SAFE_RELEASE(pCode);
  1036.           
  1037.         if( FAILED( hr = D3DXAssembleShaderFromFile(Shad3, 0, NULL, &pCode, NULL ) ) )
  1038.             goto FAIL;
  1039.         if( FAILED(hr = m_pDev->CreateVertexShader( dwDecl,(DWORD*)pCode->GetBufferPointer(), &m_dwBumpShader, 0 ) ) )
  1040.             goto FAIL;
  1041.  
  1042.         SAFE_RELEASE(pCode);
  1043.  
  1044.         //create render targets for pic-shader emulation
  1045.         if(FAILED(hr = m_pDev->CreateTexture(RENDERTARGSIZE,RENDERTARGSIZE,0,D3DUSAGE_RENDERTARGET,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&m_pRenderBuffer)))
  1046.            goto FAIL;
  1047.  
  1048.         if(FAILED(hr = m_pDev->CreateTexture(RENDERTARGSIZE,RENDERTARGSIZE,0,D3DUSAGE_RENDERTARGET,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&m_pRenderBuffer2)))
  1049.            goto FAIL;
  1050.     }
  1051.     else
  1052.     {
  1053.         //build the interleave maps, use the Alpha to
  1054.         //basis maps are not-content specific - they are just LERP tables
  1055.         if(!BuildInterleavedMap(m_pBasisTextures[0],m_pBasisMap[0],m_pBasisMap[1],m_pBasisMap[2],m_pBasisMap[3],BASISMAPSIZE,BASISMAPSIZE))
  1056.             goto FAIL;
  1057.         if(!BuildInterleavedMap(m_pBasisTextures[1],m_pBasisMap[4],m_pBasisMap[5],m_pBasisMap[6],m_pBasisMap[7],BASISMAPSIZE,BASISMAPSIZE))
  1058.             goto FAIL;
  1059.  
  1060.         if(!BuildInterleavedMap(m_pHorizonTextures[0],m_pHorizonMap[0],m_pHorizonMap[1],m_pHorizonMap[2],m_pHorizonMap[3],m_iHeightWidth,m_iHeightHeight))
  1061.             goto FAIL;
  1062.         if(!BuildInterleavedMap(m_pHorizonTextures[1],m_pHorizonMap[4],m_pHorizonMap[5],m_pHorizonMap[6],m_pHorizonMap[7],m_iHeightWidth,m_iHeightHeight))
  1063.            goto FAIL;
  1064.  
  1065.         if(FAILED(hr = D3DXFilterTexture(m_pHorizonTextures[0],NULL,0,D3DX_FILTER_BOX)))
  1066.             goto FAIL;
  1067.         if(FAILED(hr = D3DXFilterTexture(m_pHorizonTextures[1],NULL,0,D3DX_FILTER_BOX)))
  1068.             goto FAIL;
  1069.  
  1070.         //load the required shaders
  1071.         DXUtil_FindMediaFile(Shad1,_T("bumpshader4.vsh"));
  1072.         DXUtil_FindMediaFile(Shad2,_T("shadowbumpshader.psh"));
  1073.         DXUtil_FindMediaFile(Shad3,_T("bumpshader3.vsh"));
  1074.  
  1075.         if(FAILED(hr = D3DXAssembleShaderFromFile(Shad1,0,NULL, &pCode,NULL) ) )
  1076.             goto FAIL;
  1077.         if( FAILED( hr = m_pDev->CreateVertexShader( dwDecl,(DWORD*)pCode->GetBufferPointer(), &m_dwShadowShader, 0 ) ) )
  1078.             goto FAIL;
  1079.         SAFE_RELEASE(pCode);
  1080.  
  1081.         if(FAILED(hr = D3DXAssembleShaderFromFile(Shad2,0,NULL, &pCode,NULL) ) )
  1082.             goto FAIL;
  1083.         if( FAILED( hr = m_pDev->CreatePixelShader((DWORD*)pCode->GetBufferPointer(), &m_dwPixShader) ) )
  1084.             goto FAIL;
  1085.         SAFE_RELEASE(pCode);
  1086.  
  1087.         if( FAILED( hr = D3DXAssembleShaderFromFile(Shad3, 0, NULL, &pCode, NULL ) ) )
  1088.             goto FAIL;
  1089.         if( FAILED(hr = m_pDev->CreateVertexShader( dwDecl,(DWORD*)pCode->GetBufferPointer(), &m_dwBumpShader, 0 ) ) )
  1090.             goto FAIL;
  1091.  
  1092.         SAFE_RELEASE(pCode);
  1093.     }
  1094.         
  1095.     m_bInitalize = TRUE;
  1096.  
  1097.     return S_OK;
  1098. FAIL:
  1099.  
  1100.     SAFE_RELEASE(pCode);
  1101.     return E_FAIL;
  1102. }
  1103.  
  1104.  
  1105.  
  1106.  
  1107. VOID ShadowSet::DeleteDeviceObj()
  1108. {
  1109.     for(INT i=0;i<4;i++)
  1110.     {
  1111.         SAFE_RELEASE(m_pHorizonTextures[i]);
  1112.         SAFE_RELEASE(m_pBasisTextures[i]);
  1113.     }
  1114.     SAFE_RELEASE(m_pNormalMap);
  1115.     SAFE_RELEASE(m_pColorTexture);
  1116.     SAFE_RELEASE(m_pRenderBuffer);
  1117.     SAFE_RELEASE(m_pRenderBuffer2);
  1118.     SAFE_RELEASE(m_pIndexBuffer);
  1119.     SAFE_RELEASE(m_pVertices);
  1120.     SAFE_RELEASE(m_pScreenVB);
  1121.     SAFE_RELEASE(m_pShad1);
  1122.     
  1123.     if(m_pDev)
  1124.     {
  1125.         if(!m_bUsePix)
  1126.         {
  1127.             m_pDev->DeleteVertexShader(m_dwBumpShader);
  1128.             m_pDev->DeleteVertexShader(m_dwShadowShader);
  1129.             m_pDev->DeleteVertexShader(m_dwBasisShader);
  1130.         }
  1131.         else
  1132.         {
  1133.             m_pDev->DeleteVertexShader(m_dwShadowShader);
  1134.             m_pDev->DeletePixelShader(m_dwPixShader);
  1135.         }
  1136.     }
  1137. }  
  1138.  
  1139.  
  1140.  
  1141.  
  1142. VOID ShadowSet::Restore()
  1143. {
  1144.     HRESULT hr;
  1145.     SAFE_RELEASE(m_pRenderBuffer);
  1146.     SAFE_RELEASE(m_pRenderBuffer2);
  1147.  
  1148.     if(!m_bUsePix)
  1149.     {
  1150.         hr = m_pDev->CreateTexture(RENDERTARGSIZE, RENDERTARGSIZE, 0, 
  1151.             D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pRenderBuffer);
  1152.         hr = m_pDev->CreateTexture(RENDERTARGSIZE, RENDERTARGSIZE, 0, 
  1153.             D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pRenderBuffer2);
  1154.     }
  1155.  
  1156.     m_pDev->GetRenderTarget(&m_pOldRenderTarget);
  1157.     hr = m_pDev->GetDepthStencilSurface(&m_pOldStencilZ);
  1158. }
  1159.  
  1160.  
  1161.  
  1162.  
  1163. VOID ShadowSet::Invalidate()
  1164. {
  1165.     SAFE_RELEASE(m_pRenderBuffer);
  1166.     SAFE_RELEASE(m_pRenderBuffer2);
  1167.     SAFE_RELEASE(m_pOldRenderTarget);
  1168.     SAFE_RELEASE(m_pOldStencilZ);
  1169. }
  1170.  
  1171.  
  1172.  
  1173.  
  1174. // this builds a basis map
  1175. // the basis maps will be interleaved, or we will pack 3 of them into one texture
  1176. // (we could pack 4, but we can't use the alpha channel in our dot multiplies)
  1177. // but we will assume that the u,v represent the angle with respect to the center of the
  1178. // of the texture (.5,.5), So if we want the basis function for the light vector 
  1179. // (1,.5) we'd look at the point (1,.75)  
  1180. VOID ShadowSet::BuildBasisMap(BYTE *pBasis,FLOAT PrimAngle,FLOAT fAngle2)
  1181. {
  1182.     INT x,y;
  1183.     FLOAT fEndX,fEndY,fAngle,fPercent;
  1184.     FLOAT u,v,dot,nx,ny,fsq;
  1185.     BYTE *pCurLine;
  1186.  
  1187.     u = cosf(PrimAngle);
  1188.     v = sinf(PrimAngle);
  1189.  
  1190.     for(y = 0;y < BASISMAPSIZE;y++)
  1191.     {
  1192.         pCurLine = &pBasis[y*BASISMAPSIZE];
  1193.  
  1194.         for(x = 0;x < BASISMAPSIZE;x++)
  1195.         {
  1196.             fEndX =  x - .5f*BASISMAPSIZE;
  1197.             fEndY =  y - .5f*BASISMAPSIZE;
  1198.             
  1199.             //take the dot product of the normalized vectors
  1200.             fsq = sqrtf(fEndX*fEndX+fEndY*fEndY);
  1201.             if(fsq == 0)
  1202.             {
  1203.                 fPercent = 128;
  1204.             }
  1205.             else
  1206.             {
  1207.                 // we remember our definiton of dot product,
  1208.                 // cos(Angle) = DotProduct of Normalzed vectors
  1209.                 // so Angle = acos(DotProduct)
  1210.                 nx = fEndX/fsq;
  1211.                 ny = fEndY/fsq;
  1212.                 dot = nx*u + ny*v;
  1213.                 fAngle = acosf(dot);
  1214.                 if(fabs(fAngle) < fAngle2)
  1215.                 {
  1216.                     fPercent = 128 + fabsf(fAngle-fAngle2)*127/fAngle2;
  1217.                     if(fPercent>255)
  1218.                         fPercent=255;
  1219.                 }
  1220.                 else
  1221.                 {
  1222.                     fPercent = 128;
  1223.                 }
  1224.             }
  1225.             *pCurLine = (BYTE)fPercent;
  1226.             pCurLine++;
  1227.         }
  1228.     }
  1229. }
  1230.  
  1231.  
  1232.  
  1233.  
  1234. BOOL ShadowSet::BuildInterleavedMap(LPDIRECT3DTEXTURE8 &newTex,
  1235.                                     BYTE *r,
  1236.                                     BYTE *g,
  1237.                                     BYTE *b,
  1238.                                     BYTE *a,INT width,INT height)
  1239. {
  1240.     HRESULT hr;
  1241.     LPDIRECT3DTEXTURE8 pTexture;
  1242.     D3DLOCKED_RECT LockedRect;
  1243.     BYTE *pBase,*pLine;
  1244.     INT x,y;
  1245.  
  1246.     hr = D3DXCreateTexture(m_pDev, width, height, 0, 0, 
  1247.         D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture);
  1248.     if(hr != S_OK)
  1249.         return(FALSE);
  1250.  
  1251.     hr = pTexture->LockRect(0,&LockedRect,NULL,0);
  1252.     if(hr != S_OK)
  1253.     {
  1254.         pTexture->Release();
  1255.         return(FALSE);
  1256.     }
  1257.  
  1258.     pBase = (BYTE *)LockedRect.pBits;
  1259.  
  1260.     for(y = 0;y < height;y++)
  1261.     {
  1262.         pLine = &pBase[y*LockedRect.Pitch];
  1263.         for(x = 0;x < width;x++)
  1264.         {
  1265.             if(r)
  1266.                 pLine[2] = r[y*width + x];
  1267.             else
  1268.                 pLine[2] = 128;
  1269.             if(g)
  1270.                 pLine[1] = g[y*width + x];
  1271.             else
  1272.                 pLine[1] = 128;
  1273.             if(b)
  1274.                 pLine[0] = b[y*width + x];
  1275.             else
  1276.                 pLine[0] = 128;
  1277.             if(a)
  1278.                 pLine[3] = a[y*width + x];
  1279.             else
  1280.                 pLine[3] = 128;
  1281.         pLine+=4;
  1282.         }
  1283.     }
  1284.  
  1285.     pTexture->UnlockRect(0);
  1286.  
  1287.     newTex = pTexture;
  1288.  
  1289.     return TRUE;
  1290. }
  1291.  
  1292.  
  1293.  
  1294.  
  1295. #define MAPHEIGHT .175f
  1296. #define MAPHEIGHT2 .175f
  1297.  
  1298. VOID ShadowSet::BuildHorizonMap(BYTE *pHor,BYTE* pHeight,FLOAT dx,FLOAT dy,INT iStepLength,
  1299.                          INT iWidth,INT iHeight,BOOL bWrapU,BOOL bWrapV)
  1300. {
  1301.     INT x,y;
  1302.     INT imx,imy,i;
  1303.     FLOAT fpx,fpy;
  1304.     BYTE *pCurHurLine;
  1305.     FLOAT fMaxAngle,fNewAngle,fDeltaX,fDeltaY,fHeight;
  1306.  
  1307.     for(y = 0;y < iHeight;y++)
  1308.     {
  1309.         pCurHurLine = &pHor[y*iWidth];
  1310.         for(x = 0;x < iWidth;x ++)
  1311.         {
  1312.             //we assume its completly visible at zero
  1313.             fMaxAngle = 0;
  1314.             fpx = (FLOAT)x;
  1315.             fpy = (FLOAT)y;
  1316.             for(i = 0;i < iStepLength;i++)
  1317.             {
  1318.                 fpx += dx;
  1319.                 fpy += dy;
  1320.  
  1321.                 imx = (INT) fpx;
  1322.                 imy = (INT) fpy;
  1323.                 //don't check against ourselves for blocking
  1324.                 if(imx == x && imy == y)
  1325.                     continue;
  1326.                 //if we are out of bounds, we're done
  1327.                 //if the texture is repeating - this should
  1328.                 //probally wrap
  1329.                 if(imx < 0)
  1330.                 {
  1331.                     if(bWrapU)
  1332.                         imx = iWidth-1;
  1333.                     else continue;
  1334.                 }
  1335.                 
  1336.                 if(imx >= iWidth)
  1337.                 {
  1338.                     if(bWrapU)
  1339.                        imx = 0;
  1340.                     else continue;
  1341.                 }
  1342.                 
  1343.                 if(imy < 0)
  1344.                 {
  1345.                     if(bWrapV)
  1346.                        imy = iHeight-1;
  1347.                     else continue;
  1348.                 }
  1349.                 
  1350.                 if(imy >= iHeight)
  1351.                 {
  1352.                     if(bWrapV)
  1353.                         imy = 0;
  1354.                     else continue;
  1355.                 }
  1356.  
  1357.                 fDeltaX = fpx - x;
  1358.                 fDeltaY = fpy - y;
  1359.                 fHeight = pHeight[imy*iWidth+imx]*MAPHEIGHT-pHeight[y*iWidth+x]*MAPHEIGHT;
  1360.                 
  1361.                 //this is the dot prodoct
  1362.                 //Since we are dotting against the normal, (0,0,1) this is just
  1363.                 // the Height normalized, or the Height over the length of the vector
  1364.                 fNewAngle = fHeight/sqrtf(fDeltaX*fDeltaX + fDeltaY*fDeltaY + fHeight*fHeight);
  1365.             
  1366.                 //if we found a further obstruction, use it
  1367.                 if(fNewAngle > fMaxAngle)
  1368.                     fMaxAngle = fNewAngle;
  1369.             }
  1370.  
  1371.             //centered around 128
  1372.             *pCurHurLine = 128 + (BYTE) ((FLOAT)fMaxAngle*127); 
  1373.             pCurHurLine++;
  1374.         }
  1375.     }
  1376.  
  1377. }
  1378.  
  1379.  
  1380.  
  1381.  
  1382. VOID ShadowSet::ComputeLight(D3DXVECTOR3 &lightDir, 
  1383.     D3DXMATRIX *pObject, D3DXMATRIX *pView, D3DXMATRIX *pProj)
  1384. {
  1385.  
  1386.     D3DXVECTOR3 U,V,W,Pos;
  1387.     D3DXVECTOR4 light,one(1,1,1,1),half(0.5f,0.5f,.5f,.5f);//.5f);
  1388.     
  1389.     if(!m_bInitalize)
  1390.         return;
  1391.  
  1392.     light.x = lightDir.x;
  1393.     light.y = lightDir.y;
  1394.     light.z = lightDir.z;
  1395.     light.w = 0;
  1396.  
  1397.     D3DXVec4Normalize(&light,&light);
  1398.     
  1399.     m_matObject = *pObject;
  1400.     m_matView   = *pView;
  1401.     m_matProj   = *pProj;
  1402.  
  1403.     D3DXMATRIX  temp;
  1404.  
  1405.     D3DXMatrixMultiply(&m_matTot, pObject, pView);
  1406.  
  1407.     D3DXMatrixTranspose(&temp, &m_matTot);
  1408.  
  1409.     //the inverse transform
  1410.     m_pDev->SetVertexShaderConstant(   16,pObject, 4);
  1411.     
  1412.     D3DXMatrixMultiply(&m_matTot,&m_matTot,pProj);
  1413.  
  1414.     D3DXMatrixTranspose(&m_matTot,&m_matTot);
  1415.     D3DXMatrixTranspose(&m_matObject,pObject);
  1416.  
  1417.     //load the values into the registers
  1418.     m_pDev->SetVertexShaderConstant(  12, &light,  1 );
  1419.     m_pDev->SetVertexShaderConstant(  32, &one,    1);
  1420.     m_pDev->SetVertexShaderConstant(  33, &half,  1);
  1421.     m_pDev->SetVertexShaderConstant(   0, &m_matObject, 4);
  1422.     m_pDev->SetVertexShaderConstant(   8,&m_matTot, 4);
  1423. }
  1424.  
  1425.  
  1426.  
  1427.  
  1428. VOID ShadowSet::Render(BOOL bShow, BOOL bShad, BOOL bBump, INT iLeft, INT iTop,
  1429.                        INT iRight, INT iBottom)
  1430. {
  1431.     if(!m_pVertices || !m_pIndexBuffer || !m_pDev)
  1432.         return;
  1433.  
  1434.     HRESULT hr;
  1435.     INT i;
  1436.  
  1437.     VOID* pVerts;
  1438.     
  1439.     LPDIRECT3DSURFACE8 pSurface;
  1440.     
  1441.     D3DVIEWPORT8 ViewPort,OldPort;
  1442.  
  1443.     if(!m_bInitalize)
  1444.         return;
  1445.  
  1446.     static struct { FLOAT x,y,z,w, u1,v1;} s_Verts2[] =
  1447.     {
  1448.         {  RENDERTARGSIZE,   0.0f, 0.0f, 1.0f,  1,0,},
  1449.         {  RENDERTARGSIZE, RENDERTARGSIZE, 0.0f, 1.0f,  1,1,},
  1450.         {  0.0f,     0.0f, 0.0f, 1.0f,  0,0,},
  1451.         {  0.0f,   RENDERTARGSIZE, 0.0f, 1.0f,  0,1,}
  1452.     };
  1453.  
  1454.     static struct { FLOAT x,y,z,w; DWORD color;} s_Verts3[] =
  1455.     {
  1456.         {750.0f,  0.0f, 0.0f,0, D3DCOLOR_ARGB( 0xa0,0xff, 0x00, 0x00 ),},
  1457.         {750.0f, 375.0f, 0.0f,0, D3DCOLOR_ARGB( 0xa0,0xff,00, 0x00),},
  1458.         { 0.0f,  0.0f, 0.0f, 0, D3DCOLOR_ARGB( 0xa0,0xff,0x00, 0x00),},
  1459.         { 0.0f, 375.0f, 0.0f,0, D3DCOLOR_ARGB( 0xa0,0xff, 0x00, 0x00),},
  1460.     };
  1461.  
  1462.     m_pDev->SetIndices(m_pIndexBuffer,0);
  1463.  
  1464.     if(!m_bUsePix)
  1465.     {
  1466.         //sets up polygons that
  1467.         //are the same size as the screen
  1468.         //(well... almost)
  1469.         OldPort.X = iLeft;
  1470.         OldPort.Y = iTop;
  1471.         OldPort.Width = iRight-iLeft;
  1472.         OldPort.Height = iBottom-iTop;
  1473.         OldPort.MaxZ = 1;
  1474.         OldPort.MinZ = 0; 
  1475.  
  1476.         s_Verts2[0].x = (FLOAT) OldPort.Width;
  1477.         s_Verts2[1].x = (FLOAT)OldPort.Width;
  1478.         s_Verts2[1].y =(FLOAT) OldPort.Height;
  1479.         s_Verts2[3].y = (FLOAT)OldPort.Height; 
  1480.  
  1481.         s_Verts3[0].x = (FLOAT)OldPort.Width;
  1482.         s_Verts3[1].x = (FLOAT)OldPort.Width;
  1483.         s_Verts3[1].y = (FLOAT)OldPort.Height;
  1484.         s_Verts3[3].y =(FLOAT) OldPort.Height; 
  1485.  
  1486.         if(!bShow)
  1487.         {
  1488.             s_Verts3[0].color = D3DCOLOR_ARGB( 0xa0,0x00, 0x00, 0x00 );
  1489.             s_Verts3[1].color = D3DCOLOR_ARGB( 0xa0,0x00, 0x00, 0x00 );
  1490.             s_Verts3[2].color = D3DCOLOR_ARGB( 0xa0,0x00, 0x00, 0x00 );
  1491.             s_Verts3[3].color = D3DCOLOR_ARGB( 0xa0,0x00, 0x00, 0x00 ); 
  1492.         }
  1493.         else
  1494.         {
  1495.             s_Verts3[0].color = D3DCOLOR_ARGB( 0x70,0xff, 0x00, 0x00 );
  1496.             s_Verts3[1].color = D3DCOLOR_ARGB( 0x70,0xff, 0x00, 0x00 );
  1497.             s_Verts3[2].color = D3DCOLOR_ARGB( 0x70,0xff, 0x00, 0x00 );
  1498.             s_Verts3[3].color = D3DCOLOR_ARGB( 0x70,0xff, 0x00, 0x00 ); 
  1499.         }   
  1500.  
  1501.         //fill the VBs
  1502.         if(m_pShad1==NULL)
  1503.         {
  1504.            if ( FAILED( hr = m_pDev->CreateVertexBuffer( sizeof(s_Verts2),
  1505.                                  0x0, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_SYSTEMMEM, &m_pShad1 ) ) )
  1506.            {
  1507.                    goto Fail;
  1508.            }
  1509.         }
  1510.  
  1511.         if ( FAILED(hr = m_pShad1->Lock( 0, sizeof(s_Verts2), (BYTE **)(&pVerts), 0 )) )
  1512.             goto Fail;
  1513.  
  1514.         memcpy( (VOID*)pVerts, (VOID*)s_Verts2, sizeof(s_Verts2) );
  1515.     
  1516.         if (FAILED(hr = m_pShad1->Unlock()) )
  1517.            goto Fail;
  1518.  
  1519.         if(m_pScreenVB==NULL)
  1520.         {
  1521.             if ( FAILED( hr = m_pDev->CreateVertexBuffer( sizeof(s_Verts3),
  1522.                                0x0, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, D3DPOOL_SYSTEMMEM, &m_pScreenVB) ) )
  1523.             {
  1524.                  goto Fail;
  1525.             }
  1526.         }
  1527.  
  1528.         if ( FAILED(hr = m_pScreenVB->Lock( 0, sizeof(s_Verts3), (BYTE **)(&pVerts), 0 )) )
  1529.             goto Fail;
  1530.  
  1531.         memcpy( (VOID*)pVerts, (VOID*)s_Verts3, sizeof(s_Verts3) );
  1532.     
  1533.         if (FAILED(hr = m_pScreenVB->Unlock()) )
  1534.              goto Fail;
  1535.  
  1536.         m_pDev->SetRenderState(D3DRS_ZENABLE,FALSE);
  1537.  
  1538.         if(bShad)
  1539.         {
  1540.            //first set the Rendertarget
  1541.             hr =  m_pRenderBuffer->GetSurfaceLevel(0,&pSurface);
  1542.             hr =  m_pDev->SetRenderTarget(pSurface,NULL);
  1543.  
  1544.             ViewPort.X = 0;
  1545.             ViewPort.Y = 0;
  1546.             ViewPort.Height = RENDERTARGSIZE;
  1547.             ViewPort.Width =  RENDERTARGSIZE;
  1548.             ViewPort.MaxZ = 1;
  1549.             ViewPort.MinZ = 0;
  1550.  
  1551.             m_pDev->SetViewport(&ViewPort);
  1552.       
  1553.             m_pDev->Clear(0, NULL, D3DCLEAR_TARGET , D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0, 0);
  1554.     
  1555.             m_pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);  
  1556.             m_pDev->SetRenderState( D3DRS_ALPHATESTENABLE,FALSE);
  1557.  
  1558.             m_pDev->SetRenderState(D3DRS_WRAP0,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1559.             m_pDev->SetRenderState(D3DRS_WRAP1,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1560.  
  1561.             m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  1562.             m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  1563.  
  1564.             m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  1565.             m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  1566.      
  1567.             m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  1568.             m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1569.             m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1570.             m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1571.             m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  1572.     
  1573.             m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
  1574.             m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
  1575.             m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DOTPRODUCT3);   
  1576.  
  1577.             m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  1578.             m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT); //D3DTA_CURRENT);
  1579.             m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  1580.             m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  1581.  
  1582.             m_pDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1583.             m_pDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1584.  
  1585.             m_pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
  1586.             m_pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
  1587.  
  1588.             m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1589.  
  1590.             m_pDev->SetRenderState(D3DRS_WRAP0, D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1591.             m_pDev->SetRenderState(D3DRS_WRAP1, D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1592.  
  1593.             //render all the basis functions times all the images
  1594.             m_pDev->SetStreamSource( 0, m_pVertices, sizeof(ShaderVertex) );
  1595.             m_pDev->SetVertexShader(m_dwBasisShader);
  1596.             for(i = 0;i < 3;i++)
  1597.             {      
  1598.                 m_pDev->SetTexture(0, m_pHorizonTextures[i]);
  1599.                 m_pDev->SetTexture(1, m_pBasisTextures[i]);
  1600.                 hr = m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,m_iNumVertices,0,m_iNumTriangles);
  1601.             }
  1602.  
  1603.             m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  1604.  
  1605.             pSurface->Release(); 
  1606.  
  1607.             //now we have to render a simple alpha texture to subtract off for the shadow
  1608.             hr =  m_pRenderBuffer2->GetSurfaceLevel(0,&pSurface);
  1609.             hr =  m_pDev->SetRenderTarget(pSurface,NULL);
  1610.  
  1611.             m_pDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0, 0);
  1612.  
  1613.             m_pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);  
  1614.             m_pDev->SetRenderState( D3DRS_ALPHATESTENABLE,FALSE);
  1615.  
  1616.             m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  1617.  
  1618.             m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1619.             m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1620.  
  1621.             m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1622.             m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  1623.             m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1624.             m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  1625.  
  1626.             m_pDev->SetStreamSource( 0, m_pVertices, sizeof(ShaderVertex) );
  1627.             m_pDev->SetVertexShader(m_dwShadowShader);
  1628.     
  1629.             hr = m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,m_iNumVertices,0,m_iNumTriangles);
  1630.  
  1631.             //restore our states
  1632.             m_pDev->SetRenderTarget(m_pOldRenderTarget,m_pOldStencilZ);
  1633.             pSurface->Release();
  1634.             m_pDev->SetViewport(&OldPort);
  1635.         }
  1636.     }
  1637.  
  1638.     m_pDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0, 0);
  1639.     m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  1640.     m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); 
  1641.  
  1642.     m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  1643.     m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  1644.  
  1645.     m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1646.     m_pDev->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1647.  
  1648.     m_pDev->SetRenderState(D3DRS_WRAP0,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1649.     m_pDev->SetRenderState(D3DRS_WRAP1,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1650.     //important to unset a pixel shader!
  1651.     m_pDev->SetPixelShader(0);
  1652.  
  1653.     //diffuse, DOT3 lighting. 
  1654.     if(bBump)
  1655.     {
  1656.         m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  1657.         m_pDev->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1658.         m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
  1659.         m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1660.         m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  1661.         m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1662.         m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  1663.         m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  1664.  
  1665.         m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
  1666.         m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1667.         m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1);
  1668.         m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  1669.         m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
  1670.         m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  1671.         
  1672.         m_pDev->SetTexture(1,m_pColorTexture);
  1673.         m_pDev->SetTexture(0,m_pNormalMap);    
  1674.     }
  1675.     else
  1676.     {
  1677.         //no lighting, just base color texture
  1678.         m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1679.         m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1680.         m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1681.         m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  1682.         m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1683.         m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  1684.         m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  1685.         
  1686.         m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1687.         m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1688.  
  1689.         m_pDev->SetTexture(0,m_pColorTexture);
  1690.     }
  1691.  
  1692.     m_pDev->SetStreamSource( 0, m_pVertices, sizeof(ShaderVertex) );
  1693.     
  1694.     m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
  1695.     m_pDev->SetVertexShader(m_dwBumpShader);
  1696.     hr = m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,m_iNumVertices,0,m_iNumTriangles);
  1697.  
  1698.     m_pDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1699.     m_pDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1700.  
  1701.     m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  1702.     m_pDev->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE);
  1703.  
  1704.     //now apply the black mask
  1705.     if(bShad)
  1706.     {
  1707.         //emmulate pixel shaders
  1708.         //the first two passes (the basis computation and the 
  1709.         //light angle computation) were done before
  1710.         if(!m_bUsePix)
  1711.         {
  1712.             //now, subtract the light angle from the she shadow angle
  1713.             //if the value is non zero, then the pixel is in shaddow
  1714.             m_pDev->SetStreamSource(0, m_pShad1,6*sizeof(FLOAT));
  1715.             m_pDev->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_TEX1);
  1716.  
  1717.             m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  1718.  
  1719.             m_pDev->SetRenderState(D3DRS_WRAP0,0);
  1720.             m_pDev->SetRenderState(D3DRS_WRAP1,0);
  1721.  
  1722.             m_pDev->SetRenderState(D3DRS_TEXTUREFACTOR,s_Verts3[0].color);
  1723.             m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1724.             m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  1725.             m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  1726.             m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
  1727.  
  1728.             if(bShow)
  1729.                 m_pDev->SetRenderState(D3DRS_TEXTUREFACTOR,D3DCOLOR_ARGB( 0xff,0xff, 0x00, 0x00 ));
  1730.             else
  1731.                 m_pDev->SetRenderState(D3DRS_TEXTUREFACTOR,0x80202020);
  1732.  
  1733.             m_pDev->SetRenderState(D3DRS_TEXTUREFACTOR,0x60606060);
  1734.             m_pDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1735.             m_pDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SUBTRACT);
  1736.             m_pDev->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  1737.             m_pDev->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  1738.             m_pDev->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
  1739.  
  1740.             //use an alpha test - if alpha is non zero, 
  1741.             m_pDev->SetRenderState(D3DRS_ALPHATESTENABLE,TRUE);
  1742.             m_pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);    
  1743.             m_pDev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
  1744.             m_pDev->SetRenderState(D3DRS_ALPHAREF,0);
  1745.  
  1746.             m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
  1747.             m_pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);
  1748.             m_pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
  1749.  
  1750.             m_pDev->SetTexture(0, m_pRenderBuffer2);
  1751.             m_pDev->SetTexture(1, m_pRenderBuffer);
  1752.             m_pDev->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  1753.  
  1754.             m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
  1755.         }
  1756.         else
  1757.         {
  1758.              //use the pixel shader, much faster...
  1759.  
  1760.              //turn wrapping and blending on all the stages
  1761.              m_pDev->SetRenderState(D3DRS_WRAP0,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1762.              m_pDev->SetRenderState(D3DRS_WRAP1,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1763.              
  1764.              m_pDev->SetRenderState(D3DRS_WRAP2,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1765.              m_pDev->SetRenderState(D3DRS_WRAP3,D3DWRAPCOORD_0 | D3DWRAPCOORD_1);
  1766.  
  1767.              m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  1768.              m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  1769.  
  1770.              m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  1771.              m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  1772.  
  1773.              m_pDev->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  1774.              m_pDev->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  1775.              
  1776.              m_pDev->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  1777.              m_pDev->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  1778.  
  1779.              m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1780.              m_pDev->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1781.              m_pDev->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1782.              m_pDev->SetTextureStageState( 3, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  1783.              
  1784.              //bind the textures
  1785.              m_pDev->SetTexture(0, m_pHorizonTextures[0]);
  1786.              m_pDev->SetTexture(1, m_pBasisTextures[0]);
  1787.              m_pDev->SetTexture(2, m_pHorizonTextures[1]);
  1788.              m_pDev->SetTexture(3, m_pBasisTextures[1]);
  1789.  
  1790.              //render all the basis functions times all the images
  1791.              m_pDev->SetStreamSource( 0, m_pVertices, sizeof(ShaderVertex) );
  1792.              m_pDev->SetVertexShader(m_dwShadowShader);
  1793.              m_pDev->SetPixelShader(m_dwPixShader);
  1794.  
  1795.              m_pDev->SetRenderState(D3DRS_ALPHATESTENABLE,FALSE);
  1796.              m_pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);    
  1797.              m_pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCCOLOR);
  1798.              m_pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);
  1799.  
  1800.              //run the pixel shader/vertex shader
  1801.              //these will summ up all the basis maps and then compare at a per 
  1802.              //pixel level with the light angle.
  1803.              //the output is the (inverse) shadow term
  1804.              hr = m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,m_iNumVertices,0,m_iNumTriangles);
  1805.         }
  1806.     }
  1807.  
  1808. Fail:
  1809.     return;
  1810. }
  1811.  
  1812.  
  1813.  
  1814.  
  1815. //set the index and vertex buffer for the object being rendered.
  1816. VOID ShadowSet::SetBuffers(LPDIRECT3DINDEXBUFFER8 pIndex,LPDIRECT3DVERTEXBUFFER8 pVertBuffer,
  1817.                            INT iNumFaces,INT iNumVertices)
  1818. {
  1819.     m_pIndexBuffer = pIndex;
  1820.     pIndex->AddRef();
  1821.     
  1822.     m_pVertices    = pVertBuffer;
  1823.     pVertBuffer->AddRef();
  1824.  
  1825.     m_iNumTriangles = iNumFaces;
  1826.     m_iNumVertices  = iNumVertices;
  1827. }
  1828.